﻿using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

namespace ZXthex.EditorUI
{
    public class EditorRectTransform
    {
        #region code from UnityReferenceSource 
        public enum Edge { Left = 0, Right = 1, Top = 2, Bottom = 3 }
        public enum Axis { Horizontal = 0, Vertical = 1 }

        public Vector2 offsetMin
        {
            get
            {
                return anchoredPosition - Vector2.Scale(sizeDelta, pivot);
            }
            set
            {
                Vector2 offset = value - (anchoredPosition - Vector2.Scale(sizeDelta, pivot));
                sizeDelta -= offset;
                anchoredPosition += Vector2.Scale(offset, Vector2.one - pivot);
            }
        }

        public Vector2 offsetMax
        {
            get
            {
                return anchoredPosition + Vector2.Scale(sizeDelta, Vector2.one - pivot);
            }
            set
            {
                Vector2 offset = value - (anchoredPosition + Vector2.Scale(sizeDelta, Vector2.one - pivot));
                sizeDelta += offset;
                anchoredPosition += Vector2.Scale(offset, pivot);
            }
        }

        public void SetInsetAndSizeFromParentEdge(Edge edge, float inset, float size)
        {
            int axis = (edge == Edge.Top || edge == Edge.Bottom) ? 1 : 0;
            bool end = (edge == Edge.Top || edge == Edge.Right);

            // Set anchorMin and anchorMax to be anchored to the chosen edge.
            float anchorValue = end ? 1 : 0;
            Vector2 anchor = anchorMin;
            anchor[axis] = anchorValue;
            anchorMin = anchor;
            anchor = anchorMax;
            anchor[axis] = anchorValue;
            anchorMax = anchor;

            // Set size. Since anchors are together, size and sizeDelta means the same in this case.
            Vector2 sizeD = sizeDelta;
            sizeD[axis] = size;
            sizeDelta = sizeD;

            // Set inset.
            Vector2 positionCopy = anchoredPosition;
            positionCopy[axis] = end ? -inset - size * (1 - pivot[axis]) : inset + size * pivot[axis];
            anchoredPosition = positionCopy;
        }

        public void SetSizeWithCurrentAnchors(Axis axis, float size)
        {
            int i = (int)axis;
            Vector2 sizeD = sizeDelta;
            sizeD[i] = size - GetParentSize()[i] * (anchorMax[i] - anchorMin[i]);
            sizeDelta = sizeD;
        }

        private Vector2 GetParentSize()
        {
            EditorRectTransform parentRect = parent as EditorRectTransform;
            if (!parentRect)
                return Vector2.zero;
            return parentRect.rect.size;
        }
        #endregion

        public EditorRectTransform()
        {
            anchorMin = anchorMax = Vector2.one * 0.5f;
            sizeDelta = Vector2.one * 100;
            pivot = Vector2.one * 0.5f;
        }

        private bool _active = true;
        public bool activeSelf { get { return _active; } }
        public bool activeInHierarchy
        {
            get
            {
                bool active = _active;
                var node = this;
                while (true)
                {
                    if (!active)
                        return false;
                    if (node.parent == null)
                        return true;
                    node = node.parent;
                    active = node._active;
                    
                }
            }
        }
        public void SetActive(bool active)
        {
            _active = active;
        }

        public Vector2 anchorMin { get; set; }
        public Vector2 anchorMax { get; set; }
        public Vector2 anchoredPosition { get; set; }
        public Vector2 sizeDelta { get; set; }
        public Vector2 pivot { get; set; }
        public Rect rect
        {
            get
            {
                var r = new Rect();
                if (parent == null)
                {
                    r.min = Vector2.Scale(anchorMin, root.rect.size) + offsetMin;
                    r.max = Vector2.Scale(anchorMax, root.rect.size) + offsetMax;
                }
                else
                {
                    var parentRect = parent.rect;
                    r.min = parentRect.min + Vector2.Scale(anchorMin, parentRect.size) + offsetMin;
                    r.max = parentRect.min + Vector2.Scale(anchorMax, parentRect.size) + offsetMax;
                }
                return r;
            }
        }

        protected Rect guiRect
        {
            get
            {
                var r = rect;
                return new Rect(r.x, root.rect.height-(r.y+r.height), r.width, r.height);
            }
        }

        internal virtual void SelfGUI()
        {
            EditorGUI.DrawRect(guiRect, new Color(0.6f, 0.6f, 0.6f, 1));
        }

        private EditorCanvas _root;
        public EditorCanvas root
        {
            get { return _root; }
            internal set
            {
                _root = value;
            }
        }
        private EditorRectTransform parentInternal = null;
        public EditorRectTransform parent
        {
            get { return parentInternal; }
            set
            {
                SetParent(value);
            }
        }
        public void SetParent(EditorRectTransform parent)
        {
            parentInternal = parent;
            parent.children.Add(this);
            _root = parent.root;
        }

        readonly List<EditorRectTransform> children = new List<EditorRectTransform>(16);
        public int childCount
        {
            get
            {
                return children.Count;
            }
        }

        public EditorRectTransform GetChlid(int index)
        {
            if (children.Count <= index)
                throw new System.IndexOutOfRangeException(index.ToString());

            return children[index];
        }


        public static implicit operator bool(EditorRectTransform frt)
        {
            return frt != null;
        }
    }
}